using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using Domain;
using Domain.Items;
using Domain.Repository;
using Infrastructure.UnitOfWork;
using ServiceDeclaration;
using ServiceDeclaration.ViewModels;

namespace ServiceImplementation
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class ApplicationService:IApplicationService
    {
        private readonly IApplicationRepository applicationRepository;
        private readonly ITaskRepository taskRepository;
        private readonly IUserRepository userRepository;
        private readonly IApplicationManager appmanager;
        private readonly IUnitOfWorkFactory factory;

        public ApplicationService(IApplicationRepository applicationRepository, IApplicationManager appmanager, IUnitOfWorkFactory factory, ITaskRepository taskRepository, IUserRepository userRepository)
        {
            this.applicationRepository = applicationRepository;
            this.userRepository = userRepository;
            this.taskRepository = taskRepository;
            this.factory = factory;
            this.appmanager = appmanager;
            Init();
        }

        private void Init()
        {
            using (factory.Create())
            {
                var tasks = taskRepository.GetFutureTasks();
                foreach (var task in tasks)
                {
                    appmanager.QueueTask(task);
                }              
            }
        }

        IEnumerable<TaskListItem> IApplicationService.GetActiveTasks()
        {
            using (factory.Create())
            {
                var tasks =  appmanager.GetTasksInQueue();
                return tasks.Select(TaskListItem.Convert);
            }
        }

        ApplicationViewModel IApplicationService.GetApplicationInfo(int id)
        {
            using (factory.Create())
            {
                var application = applicationRepository.GetById(id);
                return ApplicationViewModel.Convert(application);
            }
        }

        public TaskViewModel GetTaskInfo(int id)
        {
            using (factory.Create())
            {
                var task = taskRepository.GetById(id);
                return TaskViewModel.Convert(task);
            }
        }

        public IEnumerable<TaskListItem> GetAllTasks()
        {
            using (factory.Create())
            {
                var tasks = taskRepository.GetAll();
                return tasks.Select(TaskListItem.Convert);
            }
        }

        public bool LaunchApplication(ApplicationViewModel application, DateTime time)
        {
            using (var unit = factory.Create())
            {
                var app = applicationRepository.GetById(application.Id);
                var task = new Task {Application = app, LaunchTime = time};
                taskRepository.Save(task);
                unit.Commit();
                return appmanager.QueueTask(task);
            }
        }

        public void KillTask(int id)
        {
            using (var unit = factory.Create())
            {
                var task = taskRepository.GetById(id);
                appmanager.RemoveTaskFromQueue(task);
                taskRepository.Delete(task);
                unit.Commit();
            }
        }

        public UserViewModel GetUserById(int id)
        {
            using (factory.Create())
            {
                return UserViewModel.Convert(userRepository.GetById(id));
            }
        }

        public IEnumerable<UserViewModel> GetUserList()
        {
            using (factory.Create())
            {
                return userRepository.GetAll().Select(UserViewModel.Convert);
            }
        }

        public void CreateUser(UserViewModel user)
        {
            using (var unit = factory.Create())
            {
                userRepository.Save(new User() {Name = user.Name, Password = user.Password});
                unit.Commit();
            }
        }

        public UserViewModel GetUserByName(string name)
        {
            using (var unit = factory.Create())
            {
                return UserViewModel.Convert(userRepository.GetByName(name));
            }
        }

        public IEnumerable<UserViewModel> GetAllUsers()
        {
            using (factory.Create())
            {
                return userRepository.GetAll().Select(UserViewModel.Convert);
            }
        }

        public void DeleteUser(UserViewModel viewModel)
        {
            using (var unit = factory.Create())
            {
                var user = userRepository.GetById(viewModel.Id) ?? userRepository.GetByName(viewModel.Name);
                userRepository.Delete(user);

                unit.Commit();

            }
        }


        public IEnumerable<ApplicationListItem> GetApplicationList()
        {
            using (factory.Create())
            {
                var applications = applicationRepository.GetAll();
                return applications.Select(ApplicationListItem.Convert);
            }
        }
    }
}